﻿#region Header
// Copyright 2007-2011, Jerónimo Milea
// 
// This file is part of NetJsWire.
// 
//     NetJsWire is free software: you can redistribute it and/or modify
//     it under the terms of the GNU General Public License as published by
//     the Free Software Foundation, either version 3 of the License, or
//     (at your option) any later version.
// 
//     NetJsWire is distributed in the hope that it will be useful,
//     but WITHOUT ANY WARRANTY; without even the implied warranty of
//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//     GNU General Public License for more details.
// 
//     You should have received a copy of the GNU General Public License
//     along with NetJsWire.  If not, see <http://www.gnu.org/licenses/>.
#endregion

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using NetJsWire.Direct.attributes;
using NetJsWire.Direct.customJsonConverter;
using NetJsWire.Direct.exceptions;
using NetJsWire.Direct.resolver;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace NetJsWire.Direct
{

    [JsonObject]
    internal class DirectResponse
    {

        private readonly int _count = -1;
        public DirectResponse( DirectRequest request, object result, OutputHandling outputHandling )
        {
            Type = request.Type;
            TransactionId = request.TransactionId;
            Action = request.Action;
            Method = request.Method;


            // TODO maybe there is a better way to avoi re parsing a string to json....
            if ( outputHandling == OutputHandling.JSON )
            {
                Result = result;
            }
            else
            {
                if ( result is IList )
                {
                    _count = ( ( IList ) result ).Count;
                }
                Result = JsonConvert.SerializeObject( result, Formatting.None, new JsonSerializerSettings { Converters = new List<JsonConverter> { new JavaScriptDateTimeConverter(), new DataRowConverter(), new DataRowViewConverter(), new DataRowCollectionConverter() }, ContractResolver = new ChangeTrackerResolver() } );
            }


            IsUpload = request.IsUpload;
        }

        public DirectResponse( DirectEvent eventObj )
        {
            Type = "event";
            Name = eventObj.name;

            Result = JsonConvert.SerializeObject( eventObj.data, Formatting.None, new JsonSerializerSettings { Converters = new List<JsonConverter> { new JavaScriptDateTimeConverter(), new DataRowConverter(), new DataRowViewConverter(), new DataRowCollectionConverter() }, ContractResolver = new ChangeTrackerResolver() } );
            //this.Result = JsonConvert.SerializeObject( eventObj.data, new JavaScriptDateTimeConverter(), new DataRowConverter(), new DataRowViewConverter(), new DataRowCollectionConverter() );
        }

        public DirectResponse( DirectRequest request, Exception e )
        {
            Type = "exception";
            TransactionId = request.TransactionId;
            Action = request.Action;
            Method = request.Method;
            Message = e.Message;
            Where = e.StackTrace;
            if ( e is DirectException )
            {
                ErrorCode = ( ( DirectException ) e ).errorCode;
            }
            Result = "{success:false}";



            IsUpload = request.IsUpload;
        }


        [JsonProperty( PropertyName = "type" )]
        public string Type
        {
            get;
            set;
        }

        [JsonProperty( PropertyName = "name" )]
        public string Name
        {
            get;
            set;
        }

        [JsonProperty( PropertyName = "tid" )]
        public int TransactionId
        {
            get;
            set;
        }

        [JsonProperty( PropertyName = "action" )]
        public string Action
        {
            get;
            set;
        }

        [JsonProperty( PropertyName = "method" )]
        public string Method
        {
            get;
            set;
        }

        [JsonProperty( PropertyName = "result" )]
        public object Result
        {
            get;
            set;
        }

        [JsonProperty( PropertyName = "where" )]
        public string Where
        {
            get;
            set;
        }

        [JsonProperty( PropertyName = "errorcode" )]
        public uint ErrorCode
        {
            get;
            set;
        }

        [JsonProperty( PropertyName = "message" )]
        public string Message
        {
            get;
            set;
        }

        [JsonIgnore]
        public bool IsUpload
        {
            get;
            private set;
        }

        public string toJson()
        {

            var sw = new StringWriter();
            var writer = new JsonTextWriter( sw );


            writer.Formatting = Formatting.None;// Indented;

            writer.QuoteChar = '"';


            // {
            writer.WriteStartObject();

            writer.WritePropertyName( "success" );
            writer.WriteValue( true );

            writer.WritePropertyName( "type" );
            writer.WriteValue( Type );

            writer.WritePropertyName( "name" );
            writer.WriteValue( Name );

            writer.WritePropertyName( "tid" );
            writer.WriteValue( TransactionId );

            writer.WritePropertyName( "action" );
            writer.WriteValue( Action );

            writer.WritePropertyName( "method" );
            writer.WriteValue( Method );

            writer.WritePropertyName( "result" );

            if ( Result == null )
            {
                writer.WriteRawValue( "null" );
            }
            else
            {
                writer.WriteRawValue( ( string ) Result );
                if ( _count >= 0 )
                {
                    writer.WritePropertyName( "Count" );
                    writer.WriteValue( _count );
                }
            }


            writer.WritePropertyName( "message" );
            writer.WriteValue( Message );


            writer.WritePropertyName( "where" );
            writer.WriteValue( Where );

            writer.WritePropertyName( "errorcode" );
            writer.WriteValue( ErrorCode );


            // }
            writer.WriteEndObject();


            var json = sw.ToString();
            sw.Close();
            return json;
            //json.Serialize(writer, value);
        }

    }
}
